 ///
 /// @file    Mystring.cc
 /// @author  lemon(haohb13@gmail.com)
 /// @date    2023-04-25 09:51:25
 ///
 
#include <string.h>

#include <vector>
#include <iostream>
using std::cout;
using std::endl;
using std::vector;

class String
{
public:
	String()
	: _pstr(new char[1]())
	{	cout << "String()" << endl;	}

    //explicit
	String(const char *pstr)
	: _pstr(new char[strlen(pstr) + 1]())
	{
		strcpy(_pstr, pstr);
		cout << "String(const char*)" << endl;
	}

    //移动构造函数
    String(String && rhs)
    : _pstr(rhs._pstr)
    {   //时间复杂为O(1)
        rhs._pstr = nullptr;
        cout << "String(String&&)" << endl;
    }

    //移动赋值运算符函数(移动赋值函数)
    String& operator=(String && rhs)
    {
        if(this != &rhs) {//1. 自移动
            cout << "String & operator=(String &&)" << endl;
            delete [] _pstr;//2. 回收左操作数申请的空间
            _pstr = rhs._pstr;//3. 移动操作
            rhs._pstr = nullptr;
        }
        return *this;//4. return*this
    }

    //拷贝构造函数
	String(const String &rhs)
	: _pstr(new char[strlen(rhs._pstr) + 1]())
	{
		strcpy(_pstr, rhs._pstr);
		cout << "String(const String&)" << endl;
	}

    //赋值运算符函数(赋值函数)
	String &operator=(const String &rhs)
	{
        cout << "String& operator=(const String&)" << endl;
		if(this != &rhs) {
			delete [] _pstr;
			_pstr = new char[strlen(rhs._pstr) + 1]();
			strcpy(_pstr, rhs._pstr);
		}
		return *this;
	}

	~String()
	{
		delete [] _pstr;
		_pstr = nullptr;
		cout << "~String()" << endl;
	}

	void print() {
		if(_pstr) {
			cout << _pstr << endl;
		}
	}
    size_t length() const { return strlen(_pstr);   }
    const char * c_str() const {    return _pstr;   }

    friend std::ostream & operator<<(std::ostream & os, const String & rhs);
private:
	char * _pstr;
};

//当用流对象对char*的空指针进行输出时，程序会直接崩溃
std::ostream & operator<<(std::ostream & os, const String & rhs)
{
    if(rhs._pstr){
        os << rhs._pstr;
    }
    return os;
}

String && func()
{   return String("wuhan"); }

void test1()
{
    //Q:右值引用本身是左值呢还是右值？
    String && ref = String("hello");
    &ref;//ok   左值
    //&func();//error 右值
}
 
void test0() 
{
    String s1("hello");
    cout << "s1: " << s1 << endl;
    printf("s1.c_str(): %p\n", s1.c_str());

    cout << "执行转移操作:" << endl;
    //该语句执行完毕之后，s1对象不会再使用,
    //将显式的将其转换成一个右值
    //std::move函数可以实现该功能
    String s2 = std::move(s1);
    //std::move其效果达到了对数据的所有权进行转移
    cout << "s1:" << s1 << endl;

    
    //假设在之后还希望重新使用s1，则必须要重新进行赋值
    s1 = "world";
    cout << "s1:" << s1 << endl;
    cout << "s2:" << s2 << endl;
    printf("s2.c_str(): %p\n", s2.c_str());

    s1 = std::move(s1);
    cout << "s1:" << s1 << endl;
}
 

 
int main(void)
{
	test0();
	return 0;
}
